#*****************************************************************************
#    # #              Name   : ZynqBuild.py
#  #     #            Date   : Jul. 15, 2021
# #    #  #  #     #  Author : Qiwei Wu
#  #     #  # #  # #  Version: 1.0
#    # #  #    #   #
# ZynqBuild.py
#
# Change History:
#  VER.   Author         DATE              Change Description
#  1.0    Qiwei Wu       Jul. 15, 2021     Initial Release
#  1.1    Qiwei Wu       Jul. 17, 2021     Add runSw and runRootfs
#*****************************************************************************
#!/usr/bin/python

import os
import sys
import time
import shutil

#*****************************************************************************
# Add persional python path
#*****************************************************************************
from Artifacts import *
from ApplyPatch import *

#*****************************************************************************
# Class
#*****************************************************************************
class ZynqBuild:

   def __init__(self, workPath, dependPath, buildPath, name=''):
      if name == '':
         print( "No path name found" )
         sys.exit( -1 )
      self.workPath = workPath
      self.dependPath = dependPath
      self.buildPath = buildPath + '/' + name + '_prebuild/'
      self.resPath = buildPath + '/' + name + '/'

   def runUboot(self):
      print( "Task Uboot is building now" )
      pathNow = os.path.abspath( os.getcwd() ) + "/"
      if os.path.exists( self.buildPath ):
         shutil.rmtree( self.buildPath )
      os.makedirs( self.buildPath )
      # Copy folder tree
      os.system( 'cp -ra %s %s' % (self.dependPath + 'u-boot-xlnx', self.buildPath) )
      # Run Uboot
      os.chdir( self.buildPath + 'u-boot-xlnx' )
      #os.system( 'git checkout xilinx-v2015.4' )
      os.system( 'patch -p1 < %s' % (self.dependPath + '../script/patchs/u-boot.patch') )
      os.system( 'patch -p1 < %s' % (self.dependPath + '../script/patchs/u-boot-loadFw.patch') )
      os.system( 'make ARCH=arm CROSS_COMPILE=/tools/Xilinx/SDK/2015.4/gnu/arm/lin/bin/arm-xilinx-linux-gnueabi- qynq_config' )
      os.system( 'make ARCH=arm CROSS_COMPILE=/tools/Xilinx/SDK/2015.4/gnu/arm/lin/bin/arm-xilinx-linux-gnueabi-' )
      # Publish artifaces
      artifacts = Artifacts( self.resPath, 'u-boot' )
      artifacts.publish( self.buildPath + 'u-boot-xlnx', 'u-boot' )
      # Remove build path
      os.chdir( pathNow )
      shutil.rmtree( self.buildPath )
      print( "Task Uboot build finished" )
      
   def runKernel(self):
      print( "Task Kernel is building now" )
      pathNow = os.path.abspath( os.getcwd() ) + "/"
      if os.path.exists( self.buildPath ):
         shutil.rmtree( self.buildPath )
      os.makedirs( self.buildPath )
      # Copy folder tree
      os.system( 'cp -ra %s %s' % (self.dependPath + 'linux-Digilent-Dev', self.buildPath) )
      # Run Kernel
      os.chdir( self.buildPath + 'linux-Digilent-Dev' )
      os.system( 'cp %s ./arch/arm/configs' % (self.workPath + 'configuration/qynq_defconfig') )
      os.system( 'cp %s ./arch/arm/boot/dts' % (self.workPath + 'configuration/qynq.dts') )
      os.system( 'make ARCH=arm CROSS_COMPILE=/tools/Xilinx/SDK/2015.4/gnu/arm/lin/bin/arm-xilinx-linux-gnueabi- qynq_defconfig uImage LOADADDR=0x00008000' )
      os.system( 'make ARCH=arm CROSS_COMPILE=/tools/Xilinx/SDK/2015.4/gnu/arm/lin/bin/arm-xilinx-linux-gnueabi-' )
      os.chdir( self.buildPath + 'linux-Digilent-Dev/arch/arm/boot/dts' )
      os.system( 'dtc -I dts -O dtb -o devicetree.dtb qynq.dts' )
      # Publish artifaces
      artifacts = Artifacts( self.resPath, 'kernel' )
      artifacts.publish( self.buildPath + 'linux-Digilent-Dev/arch/arm/boot', 'uImage' )
      artifacts.publish( self.buildPath + 'linux-Digilent-Dev/arch/arm/boot/dts', 'devicetree.dtb' )
      # Remove build path
      os.chdir( pathNow )
      shutil.rmtree( self.buildPath )
      print( "Task Kernel build finished" )
      
   def runBootbin(self, srcPath):
      print( "Task Bootbin is building now" )
      pathNow = os.path.abspath( os.getcwd() ) + "/"
      if os.path.exists( self.buildPath ):
         shutil.rmtree( self.buildPath )
      os.makedirs( self.buildPath )
      # Copy folder tree
      os.system( 'cp -f %s %s' % (srcPath + '/Platform/platform_fsbl.elf', self.buildPath) )
      os.system( 'cp -f %s %s' % (srcPath + '/Platform/platform.bit', self.buildPath + 'firmware.bit') )
      os.system( 'cp -f %s %s' % (srcPath + '/Zynq/u-boot/u-boot', self.buildPath) )
      # Run Build
      os.chdir( self.buildPath )
      os.system('cp u-boot u-boot.elf')
      with open('image.bif', 'w') as file:
         file.write('the_ROM_image:')
         file.write('{')
         file.write('   [bootloader]./platform_fsbl.elf')
         file.write('   ./u-boot.elf')
         file.write('}')
      file.close()
      with open('RunBoot.tcl', 'w') as file:
         file.write('exec bootgen -arch zynq -image image.bif -w -o BOOT.BIN')
      file.close()
      os.system('/tools/Xilinx/SDK/2015.4/bin/xsdk -batch -source RunBoot.tcl')
      # Publish artifaces
      artifacts = Artifacts( self.resPath, 'bootbin' )
      artifacts.publish( self.buildPath, 'BOOT.BIN' )
      artifacts.publish( self.buildPath, 'firmware.bit' )
      # Remove build path
      os.chdir( pathNow )
      shutil.rmtree( self.buildPath )
      print( "Task Bootbin build finished" )
      
   def runSw(self, name=''):
      if name == '':
         print( "No SW name found" )
         sys.exit( -1 )
      print( "Task SW %s is building now" %( name ) )
      pathNow = os.path.abspath( os.getcwd() ) + "/"
      if os.path.exists( self.buildPath ):
         shutil.rmtree( self.buildPath )
      os.makedirs( self.buildPath )
      # Copy folder tree
      os.system( 'cp -r %s/* %s' % (self.workPath, self.buildPath) )
      # Run Build
      if '.cgi' in name:
         os.chdir( self.buildPath + 'subsystems/cgi' )
         os.system('/tools/Xilinx/SDK/2015.4/gnu/arm/lin/bin/arm-xilinx-linux-gnueabi-gcc -I../../utils -I../../applications -I../../applications/cgic -o %s %s.c ../../applications/*.c ../../applications/cgic/*.c' %( name, name.split('.cgi')[0] ))
         # Publish artifaces
         artifacts = Artifacts( self.resPath, 'app' )
         artifacts.publish( self.buildPath + 'subsystems/cgi', name )
      else:
         os.chdir( self.buildPath + 'subsystems/app' )
         os.system('/tools/Xilinx/SDK/2015.4/gnu/arm/lin/bin/arm-xilinx-linux-gnueabi-gcc -I../../utils -I../../applications -lpthread -lsupc++ -lstdc++ -o %s %s.cpp ../../utils/*.cpp ../../applications/*.c ../../applications/*.cpp' %( name, name ))
         # Publish artifaces
         artifacts = Artifacts( self.resPath, 'app' )
         artifacts.publish( self.buildPath + 'subsystems/app', name )
      # Remove build path
      os.chdir( pathNow )
      shutil.rmtree( self.buildPath )
      print( "Task SW %s build finished" %( name ) )
      
   def runRootfs(self, srcPath, verNum='0'):
      print( "Task Rootfs is building now" )
      pathNow = os.path.abspath( os.getcwd() ) + "/"
      if os.path.exists( self.buildPath ):
         shutil.rmtree( self.buildPath )
      os.makedirs( self.buildPath )
      # Copy folder tree
      os.system( 'cp -f %s %s' % (srcPath + 'arm_ramdisk.image.gz', self.buildPath) )
      # mount image
      os.chdir( self.buildPath )
      os.system('gunzip arm_ramdisk.image.gz')
      os.system('chmod u+rwx arm_ramdisk.image')
      os.system('mkdir tmp_mnt')
      os.system('sudo mount -o loop arm_ramdisk.image tmp_mnt/')
      # Modify web
      if os.path.exists( 'tmp_mnt/var/www' ):
         os.system('sudo rm -rf tmp_mnt/var/www')
      os.system('sudo mkdir -p tmp_mnt/var/www/cgi-bin')
      # copy files
      os.system('sudo cp -raf %s/* tmp_mnt/' %( self.workPath + 'rootfs' ))
      # Insert version into WebUI
      infile = open('tmp_mnt/var/www/index.html', 'r')
      otfile = open('tmp_mnt/var/www/index_tmp.html', 'w')
      for line in infile.readlines():
         if '<h2> Platform Version </h2> ' in line:
            line = '<h2> Platform Version </h2> <p>' + verNum + '</p>'
         otfile.write(line)
      infile.close()
      otfile.close()
      os.system('mv -f %s %s' %( 'tmp_mnt/var/www/index_tmp.html', 'tmp_mnt/var/www/index.html' ))
      for path, dirs, files in os.walk( self.resPath + 'app', topdown = False ):
         for name in files:
            fileSrcPath = os.path.join( path, name )
            if '.cgi' in name:
               fileDestPath = os.path.join( self.buildPath + 'tmp_mnt/var/www/cgi-bin/', name )
            else:
               fileDestPath = os.path.join( self.buildPath + 'tmp_mnt/usr/sbin/', name )
            #shutil.copy( fileSrcPath, fileDestPath )
            os.system('sudo cp %s %s' %( fileSrcPath, fileDestPath ))
            print( "Copping %s into %s" % ( fileSrcPath, fileDestPath ) )
      # unmount image
      os.system('sudo umount tmp_mnt/')
      os.system('gzip arm_ramdisk.image')
      os.system('mkimage -A arm -T ramdisk -C gzip -d arm_ramdisk.image.gz uramdisk.image.gz')
      # Publish artifaces
      artifacts = Artifacts( self.resPath, 'rootfs' )
      artifacts.publish( self.buildPath, 'uramdisk.image.gz' )
      # Remove build path
      os.chdir( pathNow )
      shutil.rmtree( self.buildPath )
      print( "Task Roofts build finished" )
      
   def buildImage(self, verNum='0'):
      print( "Task Image is building now" )
      pathNow = os.path.abspath( os.getcwd() ) + "/"
      if os.path.exists( self.buildPath ):
         shutil.rmtree( self.buildPath )
      os.makedirs( self.buildPath )
      os.chdir( self.buildPath )
      # Copy folder tree
      os.system( 'cp -f %s %s' % (self.resPath + 'kernel/uImage', './') )
      os.system( 'cp -f %s %s' % (self.resPath + 'kernel/devicetree.dtb', './') )
      os.system( 'cp -f %s %s' % (self.resPath + 'bootbin/BOOT.BIN', './') )
      os.system( 'cp -f %s %s' % (self.resPath + 'bootbin/firmware.bit', './') )
      os.system( 'cp -f %s %s' % (self.resPath + 'rootfs/uramdisk.image.gz', './') )
      # tar
      fileName = 'platform_' + verNum + '.tar.gz'
      os.system('touch %s' %(fileName))
      os.system('tar -rvf %s %s' %( fileName, 'uImage' ))
      os.system('tar -rvf %s %s' %( fileName, 'devicetree.dtb' ))
      os.system('tar -rvf %s %s' %( fileName, 'BOOT.BIN' ))
      os.system('tar -rvf %s %s' %( fileName, 'firmware.bit' ))
      os.system('tar -rvf %s %s' %( fileName, 'uramdisk.image.gz' ))
      if os.path.exists(self.workPath + 'image'):
         for path, dirs, files in os.walk( self.workPath + 'image', topdown = False ):
            for name in files:
               fileSrcPath = os.path.join( path, name )
               fileDestPath = os.path.join( self.buildPath, name )
               shutil.copy( fileSrcPath, fileDestPath )
               os.system('tar -rvf %s %s' %( fileName, name ))
      # Publish artifaces
      artifacts = Artifacts( self.resPath, 'image' )
      artifacts.publish( self.buildPath, fileName )
      # Remove build path
      os.chdir( pathNow )
      shutil.rmtree( self.buildPath )
      print( "Task Image build finished" )
      